#include "BackpropagationSynapse.h"
#include "../Helper.h"

using namespace NeuralPlusPlus::Core::Backpropagation;
using namespace NeuralPlusPlus::Core;

NeuralPlusPlus::Core::Backpropagation::BackpropagationSynapse::BackpropagationSynapse( ActivationNeuron *sourceNeuron, ActivationNeuron *targetNeuron, BackpropagationConnector *parent )
	{
	Helper::ValidateNotNull(sourceNeuron, "sourceNeuron");
	Helper::ValidateNotNull(targetNeuron, "targetNeuron");
	Helper::ValidateNotNull(parent, "parent");

	this->Weight = 1.0;
	this->Delta = 0.0;

	sourceNeuron->TargetSynapses.push_back(this);
	targetNeuron->SourceSynapses.push_back(this);

	this->SourceNeuron = sourceNeuron;
	this->TargetNeuron = targetNeuron;
	this->Parent = parent;
	}

void NeuralPlusPlus::Core::Backpropagation::BackpropagationSynapse::Propagate()
	{
	((ActivationNeuron*)TargetNeuron)->Input += ((ActivationNeuron*)SourceNeuron)->Output * this->Weight;
	}

void NeuralPlusPlus::Core::Backpropagation::BackpropagationSynapse::OptimizeWeight( double learningFactor )
	{
	Delta = Delta * ((BackpropagationConnector*)Parent)->Momentum + learningFactor * ((ActivationNeuron*)TargetNeuron)->Error * ((ActivationNeuron*)SourceNeuron)->Output;
	Weight += Delta;
	}

void NeuralPlusPlus::Core::Backpropagation::BackpropagationSynapse::Backpropagate()
	{
	((ActivationNeuron*)SourceNeuron)->Error += ((ActivationNeuron*)TargetNeuron)->Error * this->Weight;
	}

void NeuralPlusPlus::Core::Backpropagation::BackpropagationSynapse::Jitter( double jitterNoiseLimit )
	{
	Weight += Helper::GetRandom(-jitterNoiseLimit, jitterNoiseLimit);
	}